﻿#include "TileService.h"
#include "datasource.h"
#include "DataSourceImageGDAL.h"
#include "datasourcegdaldem.h"
#include "datasourceterrain.h"
#include "datasourcetiles.h"
#include "SignalRegistry.h"
#include <qDebug>
#include "IMAGE/sqldatadb.h"

TileServiceOption::TileServiceOption(){
    taskType =Invalid;
}


TileService::TileService()
{

}

int TileService::handle(TileServiceOption &option)
{

    if(this->isRunning()) return 1;
    this->_option = option;
    this->start();
    return 0;

}

void TileService::run()
{
    DataSource* insource = 0;
    DataSource* outsource = 0;
    sqlDataDb *m_sqlDataDb =0;

    if(_option.taskType == TileServiceOption::DEM){
        insource = new DataSourceGDALDEM();
        if(_option.tileType == TileServiceOption::DEM_TERRAIN){
            outsource = new DataSourceTerrain();
        }
        else if(_option.tileType == TileServiceOption::DEM_BIL){
            outsource = new DataSourceTiles();
        }
    }
    else if(_option.taskType == TileServiceOption::IMG){
        insource = new DataSourceImageGDAL();
        if(_option.tileType == TileServiceOption::IMG_DEF){
            outsource = new DataSourceTiles();
        }
    }


    if(insource == 0 || outsource == 0) {
        SignalRegistry::instance()->signalShowMessage("ERROR TASK TYPE");
    }


    insource->setPath(_option.inputFiles[0]);
    if(!insource->open()) {
        SignalRegistry::instance()->signalShowMessage("源数据读取失败");
        return;
    };

    rxtiler::Extent dataextent = insource->getExtent();
    if(!dataextent.valid()){
        return;
    }

    insource->setTileSize(_option.tileOption.tilesize);
    outsource->setTileSize(_option.tileOption.tilesize);
    outsource->setPath(_option.outDir);
    outsource->setFileExt(_option.ext);



    int lodMin = _option.level0;
    int lodMax = _option.level1;

    std::vector<rxtiler::TileKey> tiles;

    if(_option.latlan =="WGS84")
    {
        for(int lod = lodMin; lod <= lodMax; ++lod){
            int x0 = _option.tileOption.getTileX(lod,dataextent.left);
            int x1 = _option.tileOption.getTileX(lod,dataextent.right);
            int y0 = _option.tileOption.getTileY(lod,dataextent.bottom);
            int y1 = _option.tileOption.getTileY(lod,dataextent.top);

            {
                double veryClose = _option.tileOption.getReslutionX(lod);
                double x0d = _option.tileOption.extent.left + _option.tileOption.getTileWidth(lod) * (x0+1) - dataextent.left;
                if(x0d >= 0 && x0d <= veryClose){
                    ++x0;
                }

                double x1d = dataextent.right - _option.tileOption.extent.left - _option.tileOption.getTileWidth(lod) * (x1);
                if(x1d >= 0 && x1d <= veryClose){
                    --x1;
                }
                //这里只考虑了起始点为左下角的情况
                double y0d = _option.tileOption.extent.bottom + _option.tileOption.getTileHeight(lod) * (y0+1) - dataextent.bottom;
                if(y0d >=0 && y0d <= veryClose){
                    ++y0;
                }
                double y1d = dataextent.top - _option.tileOption.extent.bottom - _option.tileOption.getTileHeight(lod) * (y1);
                if(y1d >=0 && y1d <= veryClose){
                    --y1;
                }
            }
            for(int x = x0; x <= x1; x++)
            {
                for(int y = y0; y <=y1; y++)
                {
                    tiles.push_back(rxtiler::TileKey(x,y,lod));
                }

            }
        }

    }else
    {
        for(int lod = lodMin; lod <= lodMax; ++lod){
            int x0 = 0;
            int x1 = (pow(2,(double)lod)-1);
            int y0 = 0;
            int y1 = (pow(2,(double)lod)-1);
            for(int x = x0; x <= x1; x++)
            {
                for(int y = y0; y <=y1; y++)
                {
                    tiles.push_back(rxtiler::TileKey(x,y,lod));
                }

            }
        }

    }


    SignalRegistry::instance()->signalShowMessage("Start Tiling...");
    int allsize = tiles.size();

    if(_option.ispak)
    {
        m_sqlDataDb =new  sqlDataDb() ;

        //获取pak名字与路径
        QString m_pak = _option.inputFiles[0];
        int first = m_pak.lastIndexOf ("/");
        QString title = m_pak.right (m_pak.length ()-first-1);
        first =title.lastIndexOf (".");
        title =  title.mid(0,first);
        m_pak = _option.outDir +"/" + title + ".pak";

        m_sqlDataDb->creatdb(m_pak);
        m_sqlDataDb->creatAndroid_metadata();
    }

    if(_option.taskType == TileServiceOption::IMG){
        for(int i = 0; i < tiles.size(); ++i)
        {
            rxtiler::TileKey key = tiles[i];
            rxtiler::Extent ext;
             osg::ref_ptr<osg::Image> img;
            if(_option.latlan =="WGS84")
            {
                ext =  _option.tileOption.getExtentImagePak(key);
//              qDebug() << "111111111111113";
                img = insource->getImage(key,ext);
            }else
            {

                img = insource->getImages(key,ext);
            }

//            rxtiler::Extent ext = _option.tileOption.getExtent(key);
//            osg::ref_ptr<osg::Image> img = insource->getImage(key,ext);
            if(img){
//                qDebug() << "key" <<QString(key.str().data());
                outsource->saveImage(key,img.get());
                SignalRegistry::instance()->signalShowProcess(i*100/allsize,"Handling Tile Image...");
            }
        }
        SignalRegistry::instance()->signalShowProcess(100,"Tile Image Finished!");
    }
    else if(_option.taskType == TileServiceOption::DEM){
        for(int i = 0; i < tiles.size(); ++i)
        {
            rxtiler::TileKey key = tiles[i];
            rxtiler::Extent ext = _option.tileOption.getExtent(key);
            osg::ref_ptr<osg::HeightField> dem = insource->getDEM(key,ext);
            if(dem){
                if(_option.ispak)
                {
                    if(key.lod<10)
                    {
                        if(m_sqlDataDb->IsTableExist("blocks")==false)
                        {
                            m_sqlDataDb->creatbackInfo("blocks");
                        }

                        m_sqlDataDb->addbacksinfoTerrain("blocks",key,dem,_option.tileOption.tilesize);

                    }else
                    {
                        QString m_name = m_sqlDataDb->settablename(key,_option.tileOption.tilesize);
                        if(m_sqlDataDb->IsTableExist(m_name)==false)
                        {
                            m_sqlDataDb->creatbackInfo(m_name);
                        }

                        m_sqlDataDb->addbacksinfoTerrain(m_name,key,dem,_option.tileOption.tilesize);
                    }
                }else
                {
                      outsource->saveDEM(key,dem);
                }

                SignalRegistry::instance()->signalShowProcess(i*100/allsize,"Handling Tile Dem...");
            }
        }
        SignalRegistry::instance()->signalShowProcess(100,"Tile Dem Finished!");
    }

    if(_option.ispak)
    {


        m_sqlDataDb->creattablesInfos();
        m_sqlDataDb->addInfosinfo(_option, dataextent,_option.ext);

        m_sqlDataDb->closedb();
    }else
    {
        outsource->getOrCreateMetaData()->dataExtent = dataextent;
        outsource->getOrCreateMetaData()->level0 = _option.level0;
        outsource->getOrCreateMetaData()->level1 = _option.level1;
        outsource->saveMetaData();
    }
    insource->close();
    outsource->close();

    delete insource;
    delete outsource;
}




